package com.xinsoft.jobs;

import cn.hutool.core.date.DateUtil;
import com.xinsoft.common.ApplicationContextRegister;
import com.xinsoft.common.OSinfo;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.po.SysFileHis;
import com.xinsoft.service.SysFileHisService;
import lombok.Cleanup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.Date;

/**
 * @ClassName BackUpsDBJob
 * @Description 备份数据库定时任务
 * @Author lijie
 * @Date 2023/5/11 17:08 星期四
 * @Version 1.0
 */
@Slf4j
@EnableScheduling
@Component
public class BackUpsDBJob {
    private static SysFileHisService fileHisService;

    @Autowired
    public void setSysFileHisService(SysFileHisService fileHisService) {
        BackUpsDBJob.fileHisService = fileHisService;
    }


    @Scheduled(cron = "0 0 1 * * ?") //凌晨1点开始备份数据
    private void executeInternal() {
        Environment env = ApplicationContextRegister.getBean(Environment.class);
        //定时备份数据库
        backUpDB(env);
    }

    public void backUpDB(Environment env) {
        boolean isSuccess = true;
        boolean linux = OSinfo.isLinux();
        boolean isWindows = OSinfo.isWindows();
        if (linux || isWindows) {
            String filePath = isWindows ? env.getProperty("backups.db.winFilePath") : env.getProperty("backups.db.linuxFilePath");
            String url = env.getProperty("backups.db.dbUrl");
            String dbPort = env.getProperty("backups.db.dbPort");
            String dbName = env.getProperty("backups.db.dbName");
            String username = env.getProperty("backups.db.dbUsername");
            String password = env.getProperty("backups.db.dbPassword");
            boolean isDocker = Boolean.parseBoolean(env.getProperty("backups.db.docker"));
            Long currentTime = System.currentTimeMillis();
            File uploadDir = new File(filePath);
            if (!uploadDir.exists()) {
                isSuccess = uploadDir.mkdirs();
            }
            StringBuilder cmds = new StringBuilder();

            // windows-server
//  MySQL8          --column-statistics=0
            if (isWindows && !isDocker) {
                cmds.append("cmd /c mysqldump")
                        .append(" -u")
                        .append(username)
                        .append(" -p")
                        .append(password)
                        .append(" -h")
                        .append(url)
                        .append(" -P")
                        .append(dbPort)
                        .append(" ")
                        .append(dbName)
                        .append(" > ")
                        .append(filePath)
                        .append("\\").append(dbName).append(currentTime)
                        .append(".sql");
            }


            // Linux
            if (linux && !isDocker) {
                cmds.append("mysqldump")
                        .append(" -u")
                        .append(username)
                        .append(" -p")
                        .append(password)
                        .append(" -h")
                        .append(url)
                        .append(" -P")
                        .append(dbPort)
                        .append(" ")
                        .append(dbName)
                        .append(" -r ")
                        .append(filePath)
                        .append("/")
                        .append(dbName)
                        .append(currentTime)
                        .append(".sql");
            }

            // docker 环境
            if (isDocker) {
                cmds.append("docker exec mysql mysqldump --single-transaction")
                        .append(" -u")
                        .append(username)
                        .append(" -p")
                        .append(password)
//                        .append(" -h")
//                        .append(url)
                        .append(" -P")
                        .append(dbPort)
                        .append(" ")
                        .append(dbName)
                        .append(" -r ")
                        .append(filePath)
                        .append("/")
                        .append(dbName)
                        .append(currentTime)
                        .append(".sql");
            }

            try {
                log.info("执行命令:" + cmds.toString());
                Process process = Runtime.getRuntime().exec(cmds.toString());
                if (process.waitFor() == 0) {// 0 。
                    log.info("线程正常终止");
                } else {
                    isSuccess = false;
                    log.error("命令执行失败");
                }
                process.getOutputStream().close();
                @Cleanup BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream(), "gbk"));
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = bufferedReader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
                log.info(sb.toString());
                // 开始写入标准历史
                SysFileHis fileHis = new SysFileHis();
                fileHis.setFileName(dbName + DateUtil.formatDate(new Date()) + ".sql");
                fileHis.setFileTypeId(Const.FileType.BACK_FILE);
                fileHis.setFileUploadTime(DateUtil.formatDateTime(new Date()));
                fileHis.setFileDesc("数据库备份文件：" + fileHis.getFileName() + ";生成时间：" + DateUtil.formatDateTime(new Date()));
                fileHis.setFileUrl(Const.FileTypeProxyUrl.BACK_FILE_URL + "/" + dbName +  currentTime + ".sql");
                fileHis.setCreateBy(Const.ADMIN_UID);
                fileHis.setCreateTime(new Date());
                // 自动定时任务无需填充
                fileHisService.save(fileHis);

            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
//        return isSuccess;
    }

}
